/**
 * Ajax请求工具类
 * 基于XMLHttpRequest的原生Ajax请求封装
 */

/**
 * Ajax请求配置接口
 */
export interface AjaxConfig {
  url: string;
  method?: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTIONS';
  headers?: Record<string, string>;
  data?: any;
  params?: Record<string, any>;
  timeout?: number;
  withCredentials?: boolean;
  responseType?: 'json' | 'text' | 'blob' | 'arraybuffer' | 'document';
  onUploadProgress?: (progress: number) => void;
  onDownloadProgress?: (progress: number) => void;
}

/**
 * Ajax响应数据接口
 */
export interface AjaxResponse<T = any> {
  data: T;
  status: number;
  statusText: string;
  headers: Record<string, string>;
  config: AjaxConfig;
}

/**
 * Ajax错误信息接口
 */
export interface AjaxError {
  message: string;
  status?: number;
  statusText?: string;
  data?: any;
  config?: AjaxConfig;
}

/**
 * Ajax请求类
 */
export class AjaxRequest {
  private config: AjaxConfig;

  constructor(config: AjaxConfig) {
    this.config = config;
  }

  /**
   * 发送请求
   */
  async send<T = any>(): Promise<AjaxResponse<T>> {
    return new Promise((resolve, reject) => {
      const xhr = new XMLHttpRequest();
      const { url, method = 'GET', headers = {}, data, timeout = 10000 } = this.config;

      // 设置超时
      xhr.timeout = timeout;

      // 设置请求头
      Object.entries(headers).forEach(([key, value]) => {
        xhr.setRequestHeader(key, value);
      });

      // 监听上传进度
      if (this.config.onUploadProgress) {
        xhr.upload.addEventListener('progress', (event) => {
          if (event.lengthComputable) {
            const progress = (event.loaded / event.total) * 100;
            this.config.onUploadProgress!(progress);
          }
        });
      }

      // 监听下载进度
      if (this.config.onDownloadProgress) {
        xhr.addEventListener('progress', (event) => {
          if (event.lengthComputable) {
            const progress = (event.loaded / event.total) * 100;
            this.config.onDownloadProgress!(progress);
          }
        });
      }

      // 监听状态变化
      xhr.onreadystatechange = () => {
        if (xhr.readyState === 4) {
          if (xhr.status >= 200 && xhr.status < 300) {
            const response: AjaxResponse<T> = {
              data: this.parseResponse(xhr),
              status: xhr.status,
              statusText: xhr.statusText,
              headers: this.parseHeaders(xhr.getAllResponseHeaders()),
              config: this.config
            };
            resolve(response);
          } else {
            const error: AjaxError = {
              message: `Request failed with status ${xhr.status}`,
              status: xhr.status,
              statusText: xhr.statusText,
              data: this.parseResponse(xhr),
              config: this.config
            };
            reject(error);
          }
        }
      };

      // 监听错误
      xhr.onerror = () => {
        const error: AjaxError = {
          message: 'Network error',
          config: this.config
        };
        reject(error);
      };

      // 监听超时
      xhr.ontimeout = () => {
        const error: AjaxError = {
          message: 'Request timeout',
          config: this.config
        };
        reject(error);
      };

      // 打开连接
      xhr.open(method, url, true);

      // 设置凭据
      if (this.config.withCredentials) {
        xhr.withCredentials = true;
      }

      // 发送请求
      if (data) {
        if (typeof data === 'object' && !(data instanceof FormData)) {
          xhr.setRequestHeader('Content-Type', 'application/json');
          xhr.send(JSON.stringify(data));
        } else {
          xhr.send(data);
        }
      } else {
        xhr.send();
      }
    });
  }

  /**
   * 解析响应数据
   */
  private parseResponse(xhr: XMLHttpRequest): any {
    const responseType = this.config.responseType || 'json';
    const responseText = xhr.responseText;

    switch (responseType) {
      case 'json':
        try {
          return JSON.parse(responseText);
        } catch {
          return responseText;
        }
      case 'text':
        return responseText;
      case 'blob':
        return xhr.response;
      case 'arraybuffer':
        return xhr.response;
      case 'document':
        return xhr.responseXML;
      default:
        return responseText;
    }
  }

  /**
   * 解析响应头
   */
  private parseHeaders(headersString: string): Record<string, string> {
    const headers: Record<string, string> = {};
    headersString.split('\r\n').forEach(line => {
      const parts = line.split(':');
      if (parts.length === 2) {
        headers[parts[0].trim()] = parts[1].trim();
      }
    });
    return headers;
  }
}

/**
 * Ajax客户端类
 */
export class AjaxClient {
  private baseURL: string;
  private timeout: number;
  private headers: Record<string, string>;
  private withCredentials: boolean;

  constructor(config: {
    baseURL?: string;
    timeout?: number;
    headers?: Record<string, string>;
    withCredentials?: boolean;
  } = {}) {
    this.baseURL = config.baseURL || '';
    this.timeout = config.timeout || 10000;
    this.headers = config.headers || {};
    this.withCredentials = config.withCredentials || false;
  }

  /**
   * 发送请求
   */
  async request<T = any>(config: AjaxConfig): Promise<AjaxResponse<T>> {
    // 处理URL
    const url = config.url.startsWith('http') ? config.url : this.baseURL + config.url;

    // 合并配置
    const finalConfig: AjaxConfig = {
      ...config,
      url,
      timeout: config.timeout || this.timeout,
      headers: { ...this.headers, ...config.headers },
      withCredentials: config.withCredentials ?? this.withCredentials
    };

    const request = new AjaxRequest(finalConfig);
    return request.send<T>();
  }

  /**
   * GET请求
   */
  async get<T = any>(url: string, params?: Record<string, any>, config?: Partial<AjaxConfig>): Promise<AjaxResponse<T>> {
    const queryString = params ? '?' + new URLSearchParams(params).toString() : '';
    return this.request<T>({
      ...config,
      url: url + queryString,
      method: 'GET'
    });
  }

  /**
   * POST请求
   */
  async post<T = any>(url: string, data?: any, config?: Partial<AjaxConfig>): Promise<AjaxResponse<T>> {
    return this.request<T>({
      ...config,
      url,
      method: 'POST',
      data
    });
  }

  /**
   * PUT请求
   */
  async put<T = any>(url: string, data?: any, config?: Partial<AjaxConfig>): Promise<AjaxResponse<T>> {
    return this.request<T>({
      ...config,
      url,
      method: 'PUT',
      data
    });
  }

  /**
   * DELETE请求
   */
  async delete<T = any>(url: string, config?: Partial<AjaxConfig>): Promise<AjaxResponse<T>> {
    return this.request<T>({
      ...config,
      url,
      method: 'DELETE'
    });
  }

  /**
   * PATCH请求
   */
  async patch<T = any>(url: string, data?: any, config?: Partial<AjaxConfig>): Promise<AjaxResponse<T>> {
    return this.request<T>({
      ...config,
      url,
      method: 'PATCH',
      data
    });
  }
}

/**
 * 创建Ajax客户端
 */
export function createAjaxClient(config?: {
  baseURL?: string;
  timeout?: number;
  headers?: Record<string, string>;
  withCredentials?: boolean;
}): AjaxClient {
  return new AjaxClient(config);
}

/**
 * 快速Ajax请求方法
 */
export const ajax = {
  /**
   * 创建Ajax客户端
   */
  createClient: createAjaxClient,
  
  /**
   * 快速GET请求
   */
  get: async <T = any>(url: string, params?: Record<string, any>): Promise<AjaxResponse<T>> => {
    const client = createAjaxClient();
    return client.get<T>(url, params);
  },
  
  /**
   * 快速POST请求
   */
  post: async <T = any>(url: string, data?: any): Promise<AjaxResponse<T>> => {
    const client = createAjaxClient();
    return client.post<T>(url, data);
  },
  
  /**
   * 快速PUT请求
   */
  put: async <T = any>(url: string, data?: any): Promise<AjaxResponse<T>> => {
    const client = createAjaxClient();
    return client.put<T>(url, data);
  },
  
  /**
   * 快速DELETE请求
   */
  delete: async <T = any>(url: string): Promise<AjaxResponse<T>> => {
    const client = createAjaxClient();
    return client.delete<T>(url);
  }
};
